package com.mytecblog.framework.dao.impl;

import com.mytecblog.framework.dao.IBaseDao;
import com.mytecblog.framework.dao.query.DBQuery;
import com.mytecblog.framework.dao.query.HQLDBQuery;
import com.mytecblog.framework.dao.query.SQLDBQuery;
import com.mytecblog.framework.entity.MetaObject;
import com.mytecblog.framework.util.GenericsUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Query;;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;

/**
 * 基础Dao层接口的实现类
 * @param <T>  范型，指实体类
 * @author 黄永光
 * @version 1.0
 */
@Repository
public abstract class BaseDaoImpl<T extends MetaObject> implements IBaseDao<T> {

    @Autowired()
    protected SessionFactory sessionFactory;
    /**
     * 实体类对应的类
     */
    protected Class<T> entityClass;

    public BaseDaoImpl() {
        //使用反射技术得到T的真实类型
        //获取当前new的对象的泛型的父类

        //获取第一个类型参数的真实类型
        this.entityClass = GenericsUtil.getSuperClassGenricType(this.getClass(),0);
    }

    public T get(long id) {
        return this.getSession().get(entityClass, id);
    }


    public void save(MetaObject entity) {
        getSession().saveOrUpdate(entity);
    }


    public void delete(T entity) {
        this.getSession().delete(entity);
    }

    /**
     * 删除实体
     *
     * @param id 实体的ID
     */
    public void delete(long id) {
        getSession().delete(get(id));
    }
    /**
     * 更新实体
     * 可用于添加、修改、删除操作
     *
     * @param hql    更新的HQL语句
     * @param params 参数,可有项目或多项目,代替Hql中的"?"号
     */
    protected void update(final String hql, final Object... params) {
        Query query = getSession().createQuery(hql);
        for (int i = 0; i < params.length; i++) {
            query.setParameter(i, params[i]);
        }
        query.executeUpdate();
    }


    /**
     * 查询全部记录列表
     * @return 记录List集
     */
    public List<T> findAll(final String orderBy) {
        DBQuery<T>  query=this.createQuery(" from "+entityClass.getName()+" ",new Object[]{});
        query.setOrderBy(orderBy);
        return  query.getResult();
    }

    /**
     * 根据属性值查询列表
     *
     * @param propertyName 属性名
     * @param value        属性值
     * @return List列表
     */
    public List<T> findByProperty(String propertyName, Object value) {
        String hql=" from "+entityClass.getName()+"  where "+propertyName+"=?";
        return this.createQuery(hql,new Object[]{value}).getResult();
    }

    /**
     * 根据属性值查询单个对象
     *
     * @param propertyName 属性名
     * @param value        属性值
     * @return 实体对象
     */

    public T findUniqueByProperty(final String propertyName, final Object value) {
       List<T> results=this.findByProperty(propertyName,value);
        return results.size()>0?results.get(0):null;
    }
    /**
     * @param hql    查询语句
     *               用法如：可用于登录验证时，根据用户名、密码等信息查询用户
     * @param params 参数数组,代替HQL中的"?"号,可有0项目或多项
     * @return 唯一实体，返回null则表示不存在配置的实体
     */

    protected T findUniqueByHql(final String hql, final Object... params) {
        DBQuery query = this.createQuery(hql,params);
        T result = (T) query.uniqueResult();
        return result;
    }

    /**
     * 按HQL条件查询列表
     *
     * @param hql    查询语句,支持连接查询和多条件查询
     * @param params 参数数组,代替hql中的"?"号
     * @return 结果集List
     */

    protected List<T> findByHql(String hql, Object... params) {
        DBQuery<T> query=this.createQuery(hql,params);
        return query.getResult();
    }

    /**
     * 创建sql 查询
     * 受保护的方法，只允许子类调用
     * @param sql
     * @param params 查询参数
     * @return
     */
    protected   List<Map> findBySql(String sql,Object... params){
        return  this.createSqlQuery(sql,params).getResult();
    }




    /**
     * 创建查询
     * 受保护的方法，只允许子类调用
     * @param hql
     * @param params
     * @return
     */
    protected DBQuery createQuery(String hql, Object[] params) {
        return new HQLDBQuery(this.entityClass,hql,this.getSession());
    }
    /**
     * 创建查询
     * 受保护的方法，只允许子类调用
     * @param hql
     * @param params
     * @return
     */
    protected DBQuery createQuery(String hql, Map<String, Object> params) {
        return new HQLDBQuery(entityClass,hql,this.getSession());
    }

    /**
     * 创建sql查询
     * @param sql sql查询语句
     * @param params
     * @return
     */
    protected DBQuery createSqlQuery(String sql, Object[] params) {
        return new SQLDBQuery(sql,this.getSession()).setParameters(params);
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }


    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Session getSession() {
        return this.sessionFactory.getCurrentSession();
    }
}

